dnd: Allow programmatic drag cancellation
authorMatthias Clasen <mclasen@redhat.com>
Fri, 30 Jan 2015 04:49:48 +0000 (23:49 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Fri, 30 Jan 2015 14:38:41 +0000 (09:38 -0500)
Add a gtk_drag_cancel() function that can be used on the
source side to cancel an ongoing drag operation. This can
be useful, e.g. if the data that is being dragged becomes
unavailable.

docs/reference/gtk/gtk3-sections.txt
gtk/gtkdnd.c
gtk/gtkdnd.h

index 748f1be6ab5b617a3b23f784d991ceac12a286dd..55c9f54e04720e90b03806d8527659cd6a2210db 100644 (file)
@@ -6536,6 +6536,7 @@ gtk_drag_unhighlight
 <SUBSECTION Source Side>
 gtk_drag_begin
 gtk_drag_begin_with_coordinates
+gtk_drag_cancel
 gtk_drag_set_icon_widget
 gtk_drag_set_icon_pixbuf
 gtk_drag_set_icon_stock
index 8ee832f07cc367a5f68e899ebd7325ec483feaf0..6e829d14ed43b6d49d0138368f9576b06dd83a12 100644 (file)
@@ -245,7 +245,7 @@ static void gtk_drag_drop                      (GtkDragSourceInfo *info,
 static void gtk_drag_drop_finished             (GtkDragSourceInfo *info,
                                                 GtkDragResult      result,
                                                 guint              time);
-static void gtk_drag_cancel                    (GtkDragSourceInfo *info,
+static void gtk_drag_cancel_internal           (GtkDragSourceInfo *info,
                                                 GtkDragResult      result,
                                                 guint32            time);
 
@@ -4226,9 +4226,9 @@ gtk_drag_end (GtkDragSourceInfo *info,
  * or programmatically.
  */
 static void
-gtk_drag_cancel (GtkDragSourceInfo *info,
-                 GtkDragResult      result,
-                 guint32            time)
+gtk_drag_cancel_internal (GtkDragSourceInfo *info,
+                          GtkDragResult      result,
+                          guint32            time)
 {
   gtk_drag_end (info, time);
   gdk_drag_abort (info->context, time);
@@ -4285,7 +4285,7 @@ gtk_drag_key_cb (GtkWidget   *widget,
       switch (event->keyval)
         {
         case GDK_KEY_Escape:
-          gtk_drag_cancel (info, GTK_DRAG_RESULT_USER_CANCELLED, event->time);
+          gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_USER_CANCELLED, event->time);
           return TRUE;
 
         case GDK_KEY_space:
@@ -4301,7 +4301,7 @@ gtk_drag_key_cb (GtkWidget   *widget,
             }
           else
             {
-              gtk_drag_cancel (info, GTK_DRAG_RESULT_NO_TARGET, event->time);
+              gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_NO_TARGET, event->time);
             }
 
           return TRUE;
@@ -4368,7 +4368,7 @@ gtk_drag_grab_broken_event_cb (GtkWidget          *widget,
       || event->grab_window == gtk_widget_get_window (info->ipc_widget))
     return FALSE;
 
-  gtk_drag_cancel (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ());
+  gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ());
   return TRUE;
 }
 
@@ -4385,9 +4385,10 @@ gtk_drag_grab_notify_cb (GtkWidget *widget,
   if (gtk_widget_device_is_shadowed (widget, pointer))
     {
       /* We have to block callbacks to avoid recursion here, because
-         gtk_drag_cancel calls gtk_grab_remove (via gtk_drag_end) */
+       * gtk_drag_cancel_internal calls gtk_grab_remove (via gtk_drag_end)
+       */
       g_signal_handlers_block_by_func (widget, gtk_drag_grab_notify_cb, data);
-      gtk_drag_cancel (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ());
+      gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_GRAB_BROKEN, gtk_get_current_event_time ());
       g_signal_handlers_unblock_by_func (widget, gtk_drag_grab_notify_cb, data);
     }
 }
@@ -4411,7 +4412,7 @@ gtk_drag_button_release_cb (GtkWidget      *widget,
     }
   else
     {
-      gtk_drag_cancel (info, GTK_DRAG_RESULT_NO_TARGET, event->time);
+      gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_NO_TARGET, event->time);
     }
 
   return TRUE;
@@ -4464,3 +4465,34 @@ gtk_drag_check_threshold (GtkWidget *widget,
   return (ABS (current_x - start_x) > drag_threshold ||
           ABS (current_y - start_y) > drag_threshold);
 }
+
+/**
+ * gtk_drag_cancel:
+ * @context: a #GdkDragContext, as e.g. returned by gtk_drag_begin_with_coordinates()
+ *
+ * Cancels an ongoing drag operation on the source side.
+ *
+ * If you want to be able to cancel a drag operation in this way,
+ * you need to keep a pointer to the drag context, either from an
+ * explicit call to gtk_drag_begin_with_coordinates(), or by
+ * connecting to #GtkWidget::drag-begin.
+ *
+ * If @context does not refer to an ongoing drag operation, this
+ * function does nothing.
+ *
+ * If a drag is cancelled in this way, the @result argument of
+ * #GtkWidget::drag-failed is set to @GTK_DRAG_RESULT_ERROR.
+ *
+ * Since: 3.16
+ */
+void
+gtk_drag_cancel (GdkDragContext *context)
+{
+  GtkDragSourceInfo *info;
+
+  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
+
+  info = gtk_drag_get_source_info (context, FALSE);
+  if (info != NULL)
+    gtk_drag_cancel_internal (info, GTK_DRAG_RESULT_ERROR, gtk_get_current_event_time ());
+}
index de328dbccfbc7b2d714e5b63fe89812ac2349d21..5f7c4eb442bef6b89fa9f271d961c3b35c2c5352 100644 (file)
@@ -203,6 +203,9 @@ GdkDragContext *gtk_drag_begin (GtkWidget         *widget,
                                gint               button,
                                GdkEvent          *event);
 
+GDK_AVAILABLE_IN_3_16
+void gtk_drag_cancel           (GdkDragContext *context);
+
 /* Set the image being dragged around
  */
 GDK_AVAILABLE_IN_ALL